#ifndef __I_NGISDATA_UDXSCHEMA_DESCRIPTION_H__
#define __I_NGISDATA_UDXSCHEMA_DESCRIPTION_H__

#include "INxUnknown.h"
#include <string>

namespace NGIS
{
	namespace Data
	{
		namespace Schema
		{
			enum ESchemaNodeType
			{
				EDTKT_INT = 2,				//!<integer
				EDTKT_REAL = 4,				//!<float with 64bit precise
				EDTKT_VECTOR2 = 8,		//!<2 dimensions vector with x and y
				EDTKT_VECTOR3 = 16,		//!<3 dimensions vector with x, y and z
				EDTKT_VECTOR4 = 32,		//!<4 dimensions vector with x, y, z and w
				EDTKT_STRING = 64,			//!<a string with NULL terminated
				EDTKT_NODE = 128,			//!<a no-constraints node container
				EDTKT_LIST = 256,				//!<a container with same structure node
				EDTKT_MAP = 512,				//!<a k-v map container
				EDTKT_TABLE = 1024			//!<a data table container
			};

			static const char* SchemaNodeType2String(ESchemaNodeType pType)
			{
				if (pType == ESchemaNodeType::EDTKT_INT)
					return "DTKT_INT";
				else if (pType == ESchemaNodeType::EDTKT_REAL)
					return "DTKT_REAL";
				else if (pType == ESchemaNodeType::EDTKT_VECTOR2)
					return "DTKT_VECTOR2D";
				else if (pType == ESchemaNodeType::EDTKT_VECTOR3)
					return "DTKT_VECTOR3D";
				else if (pType == ESchemaNodeType::EDTKT_VECTOR4)
					return "DTKT_VECTOR4D";
				else if (pType == ESchemaNodeType::EDTKT_STRING)
					return "DTKT_STRING";
				else if (pType == (ESchemaNodeType::EDTKT_INT | ESchemaNodeType::EDTKT_LIST))
					return "DTKT_INT | DTKT_LIST";
				else if (pType == (ESchemaNodeType::EDTKT_REAL | ESchemaNodeType::EDTKT_LIST))
					return "DTKT_REAL | DTKT_LIST";
				else if (pType == (ESchemaNodeType::EDTKT_VECTOR2 | ESchemaNodeType::EDTKT_LIST))
					return "DTKT_VECTOR2D | DTKT_LIST";
				else if (pType == (ESchemaNodeType::EDTKT_VECTOR3 | ESchemaNodeType::EDTKT_LIST))
					return "DTKT_VECTOR3D | DTKT_LIST";
				else if (pType == (ESchemaNodeType::EDTKT_VECTOR4 | ESchemaNodeType::EDTKT_LIST))
					return "DTKT_VECTOR4D | DTKT_LIST";
				else if (pType == (ESchemaNodeType::EDTKT_STRING | ESchemaNodeType::EDTKT_LIST))
					return "DTKT_STRING | DTKT_LIST";
				else if (pType == ESchemaNodeType::EDTKT_NODE)
					return "DTKT_ANY";
				else if (pType == ESchemaNodeType::EDTKT_LIST)
					return "DTKT_LIST";
				else if (pType == ESchemaNodeType::EDTKT_MAP)
					return "DTKT_MAP";
				else if (pType == ESchemaNodeType::EDTKT_TABLE)
					return "DTKT_TABLE";
			}

			static ESchemaNodeType String2SchemaNodeType(const char* pType)
			{
				std::string pTypeStr = pType;
				ESchemaNodeType pNodeType = ESchemaNodeType::EDTKT_NODE;
				if (pTypeStr == "DTKT_INT")
					pNodeType = ESchemaNodeType::EDTKT_INT;
				else if (pTypeStr == "DTKT_REAL")
					pNodeType = ESchemaNodeType::EDTKT_REAL;
				else if (pTypeStr == "DTKT_VECTOR2D")
					pNodeType = ESchemaNodeType::EDTKT_VECTOR2;
				else if (pTypeStr == "DTKT_VECTOR3D")
					pNodeType = ESchemaNodeType::EDTKT_VECTOR3;
				else if (pTypeStr == "DTKT_VECTOR4D")
					pNodeType = ESchemaNodeType::EDTKT_VECTOR4;
				else if (pTypeStr == "DTKT_STRING")
					pNodeType = ESchemaNodeType::EDTKT_STRING;
				else if (pTypeStr == "DTKT_INT | DTKT_LIST")
					pNodeType = (ESchemaNodeType)(ESchemaNodeType::EDTKT_INT | ESchemaNodeType::EDTKT_LIST);
				else if (pTypeStr == "DTKT_REAL | DTKT_LIST")
					pNodeType = (ESchemaNodeType)(ESchemaNodeType::EDTKT_REAL | ESchemaNodeType::EDTKT_LIST);
				else if (pTypeStr == "DTKT_VECTOR2D | DTKT_LIST")
					pNodeType = (ESchemaNodeType)(ESchemaNodeType::EDTKT_VECTOR2 | ESchemaNodeType::EDTKT_LIST);
				else if (pTypeStr == "DTKT_VECTOR3D | DTKT_LIST")
					pNodeType = (ESchemaNodeType)(ESchemaNodeType::EDTKT_VECTOR3 | ESchemaNodeType::EDTKT_LIST);
				else if (pTypeStr == "DTKT_VECTOR4D | DTKT_LIST")
					pNodeType = (ESchemaNodeType)(ESchemaNodeType::EDTKT_VECTOR4 | ESchemaNodeType::EDTKT_LIST);
				else if (pTypeStr == "DTKT_STRING | DTKT_LIST")
					pNodeType = (ESchemaNodeType)(ESchemaNodeType::EDTKT_STRING | ESchemaNodeType::EDTKT_LIST);
				else if (pTypeStr == "DTKT_ANY")
					pNodeType = ESchemaNodeType::EDTKT_NODE;
				else if (pTypeStr == "DTKT_LIST")
					pNodeType = ESchemaNodeType::EDTKT_LIST;
				else if (pTypeStr == "DTKT_MAP")
					pNodeType = ESchemaNodeType::EDTKT_MAP;
				else if (pTypeStr == "DTKT_TABLE")
					pNodeType = ESchemaNodeType::EDTKT_TABLE;

				return pNodeType;
			}

			class INodeDescription : public INxUnknown
			{
			public:
				virtual ESchemaNodeType getKernelType() = 0;

				virtual bool modifyKernelType(ESchemaNodeType pKernelType) = 0;

				virtual const char* getNodeDescription() = 0;

				virtual bool modifyNodeDescription(const char* pNodeInfo) = 0;

				//////////////////////////////////////////////////////////////////////////
				virtual const char* getConceptTag() = 0;

				virtual bool modifyConceptTag(const char* pTag) = 0;

				virtual const char* getUnitTag() = 0;

				virtual bool modifyUnitTag(const char* pTag) = 0;

				virtual const char* getDimensionTag() = 0;

				virtual bool modifyDimensionTag(const char* pTag) = 0;

				virtual const char* getSpatialReferencefTag() = 0;

				virtual bool modifySpatialReferenceTag(const char* pTag) = 0;

				virtual const char* getDataTemplateTag() = 0;

				virtual bool modifyDataTemplateTag(const char* pTag) = 0;
			};
		}
	}
}

#endif